package com.huadao.cart_ccs.netty;

import android.util.Log;

import com.huadao.cart_ccs.common.ByteUtils;
import com.huadao.cart_ccs.common.ExperimentStageManager;
import com.huadao.cart_ccs.common.ProjectManager;
import com.huadao.cart_ccs.data.bo.CommandWord;
import com.huadao.cart_ccs.data.bo.Protocol;
import com.huadao.cart_ccs.exception.ExceptionCode;
import com.huadao.cart_ccs.exception.ProtocolException;
import com.huadao.cart_ccs.exception.UnpackException;

import java.util.Arrays;
import java.util.Date;


public class TestDecoder {

    private static final String TAG="TestDecoder";
    public static final byte[] HEAD=new byte[]{(byte) 0xBA};
    public static final byte[] TAIL=new byte[]{(byte) 0xED};

    public static final int headLength=1;
    public static final int lengthLength=2;
    public static final int agentNumberLength=2;
    public static final int MACLength=6;
    public static final int deviceTypeLength=1;
    public static final int commandWordLength=1;
    public static final int modularOrderLength=3;
    public int orderContentLength;
    public static final int checkSumLength=1;
    public static final int tailLength=1;

    //    private ProtocolDao protocolDao;
//    public TestDecoder() {
//        protocolDao=GreenDaoManager.getInstance().getNoCacheSession().getProtocolDao();
//    }

    public Protocol decode(byte[] bytes) throws UnpackException, ProtocolException {
        String responseStr=ByteUtils.getHexByte(bytes,0,bytes.length);
        Log.i(TAG,responseStr);

        int index = 0;
        int length=bytes.length;
        if(length<headLength+tailLength){
            throw new UnpackException("response length:"+ length + "too short",bytes);
        }

        byte[] head= Arrays.copyOfRange(bytes,0, index +=headLength);//报头
        if(!ByteUtils.isEqual(head,HEAD)){
            throw new ProtocolException("wrong head:"+ ByteUtils.getHexByte(head,0,head.length), ExceptionCode.HEAD,bytes);
        }

        byte[] resLength;
        if(bytes.length- index <lengthLength){
            throw new ProtocolException("wrong content length",ExceptionCode.LENGTH,bytes);
        }else {
            resLength = Arrays.copyOfRange(bytes, index, index +=lengthLength);//报文长度
            int contentLength=ByteUtils.bytes2intHL(resLength);
//            int actualLength=contentLength+headLength+tailLength+lengthLength;
//            if(actualLength!=length){
//                throw new ProtocolException("wrong length",ProtocolException.LENGTH);
//            }
            int actualLength=length-headLength-tailLength-lengthLength;
            if(actualLength!=contentLength){
                //解析到的报文长度和实际计算出的长度不等
                throw new ProtocolException("wrong length",ExceptionCode.LENGTH,bytes);
            }
            if(contentLength<agentNumberLength+MACLength+deviceTypeLength+commandWordLength+modularOrderLength+1+checkSumLength){//orderContent的长度至少为1
                //解析到的报文长度小于最小值，可能部分字段缺失
                throw new ProtocolException("length less than minimum length",ExceptionCode.LENGTH,bytes);
            }
            orderContentLength=contentLength-agentNumberLength-MACLength-deviceTypeLength-commandWordLength-modularOrderLength-checkSumLength;
        }

        byte[] agentNumber;
        if(bytes.length- index <agentNumberLength){
            throw new ProtocolException("wrong agentNumber",ExceptionCode.AGENT_CODE,bytes);
        }else {
            agentNumber=Arrays.copyOfRange(bytes, index, index +=agentNumberLength);//代理商编号
        }

        byte[] mac;
        if(bytes.length- index <MACLength){
            throw new ProtocolException("wrong MAC",ExceptionCode.MAC,bytes);
        }else {
            mac=Arrays.copyOfRange(bytes, index, index +=MACLength);//MAC地址
        }

        byte[] deviceType;
        if(bytes.length- index <deviceTypeLength){
            throw new ProtocolException("wrong deviceType",ExceptionCode.DEVICE_TYPE,bytes);
        }else {
            deviceType=Arrays.copyOfRange(bytes, index, index +=deviceTypeLength);//设备类型
        }

        byte[] commandWord;
        if(bytes.length- index <commandWordLength){
            throw new ProtocolException("wrong commandWord",ExceptionCode.COMMOND_WORD,bytes);
        }else {
            commandWord=Arrays.copyOfRange(bytes, index, index +=commandWordLength);//命令字
            if(!isCommandWordLegal(commandWord)){
                throw new ProtocolException("wrong command word:"+ByteUtils.getHexByte(commandWord,0,commandWord.length),ExceptionCode.COMMOND_WORD,bytes);
            }
        }

        byte[] modularOrder;
        if(bytes.length- index <modularOrderLength){
            throw new ProtocolException("wrong modularOrder",ExceptionCode.MODULAR_ORDER,bytes);
        }else {
            modularOrder=Arrays.copyOfRange(bytes, index, index +=modularOrderLength);//模块指令
        }

        byte[] orderContent;
        if(bytes.length- index <orderContentLength){
            throw new ProtocolException("wrong orderContent",ExceptionCode.ORDER_CONTENT,bytes);
        }else {
            orderContent=Arrays.copyOfRange(bytes, index, index +=orderContentLength);//指令内容
        }

        byte[] checkSum;
        if(bytes.length- index <checkSumLength){
            throw new ProtocolException("wrong checkSum",ExceptionCode.CHECKSUM,bytes);
        }else {
            checkSum=Arrays.copyOfRange(bytes, index, index +=checkSumLength);//校验和
        }

        byte[] tail;
        if(bytes.length- index <tailLength){
            throw new ProtocolException("wrong tail",ExceptionCode.TAIL,bytes);
        }else {
            tail=Arrays.copyOfRange(bytes, index, index +=tailLength);//报尾
            if(!ByteUtils.isEqual(tail,TAIL)){
                throw new ProtocolException("wrong tail:"+ ByteUtils.getHexByte(head,0,tail.length),ExceptionCode.TAIL,bytes);
            }
        }

        //测试时为了方便测试，不校验
        byte sum=ByteUtils.calculateSum(resLength,agentNumber,mac,deviceType,commandWord,modularOrder,orderContent);
        if(sum!=checkSum[0]){
            throw new ProtocolException("wrong checkSum",ExceptionCode.CHECKSUM,bytes);
        }

        Protocol protocol=new Protocol(head,resLength,agentNumber,mac,deviceType,commandWord,modularOrder,orderContent,checkSum,tail);
        protocol.setType(Protocol.type_response);
        protocol.setDate(new Date());
        protocol.setProjectId(ProjectManager.getInstance().getProjectId());
        protocol.setStageId(ExperimentStageManager.getInstance().getStageId());
        return protocol;
    }

    private boolean isCommandWordLegal(byte[] commandWord){
        if(ByteUtils.isEqual(commandWord, CommandWord.readSucc)){
            return true;
        }else if(ByteUtils.isEqual(commandWord, CommandWord.writeSucc)){
            return true;
        }else if(ByteUtils.isEqual(commandWord, CommandWord.readFail)){
            return true;
        }else if(ByteUtils.isEqual(commandWord, CommandWord.writeFail)){
            return true;
        }
        return false;
    }
}

